<?php

/**
 * User: roman
 * Date: 23.06.11
 * Time: 19:32
 */

namespace Managers;

class Connects extends BaseManager
{

    protected $__table = '\Catalog\Connect';
    private $__itemsTable = '\Catalog\Items';
    private $__tagsTable = '\Catalog\Tags';

    public function getList()
    {

        $res = $this->_getCacheManager()->load('res');

        if (!$res) {

            $res = $this->_em->createQueryBuilder()

                    ->select('con', 'i', 'tag', 'gr')
                    ->from($this->__table, 'con')
                    ->join('con.item', 'i')
                    ->join('con.tag', 'tag')
                    ->join('tag.group', 'gr')
                    ->getQuery()
                    ->getArrayResult();

            $this->_getCacheManager()->save($res, 'res', array(), 60);
        }

        return $res;
    }

    /**
     * Получаем одну запись с заданными ID итема и ID тэга.
     * @param $item_id ID итема
     * @param $tag_id ID тэга
     * @return ID коннекта с заданным ID итема и ID тэга.
     */
    public function getOne($item_id, $tag_id)
    {

        $res = $this->_em->createQueryBuilder()
                ->select('con')
                ->from($this->__table, 'con')
                ->where('con.tag = :tag_id and con.item = :item_id')
                ->setParameters(array('tag_id' => $tag_id, 'item_id' => $item_id))
                ->getQuery()
                ->getArrayResult();

        return $res[0];
    }

    /**
     * Получаем массив тэгов к заданному итему.
     * @param $item_id ID итема.
     * @return array ID тэгов.
     */
    public function getTags($item_id)
    {

        $result = $this->_em->createQueryBuilder()
                ->select('tag.id', 'tag.name')
                ->from($this->__table, 'con')
                ->join('con.tag', 'tag')
                ->where('con.item = :id')
                ->setParameter('id', $item_id)
                ->getQuery()
                ->getArrayResult();

        return $result;

    }

    /**
     * Обновляем список тэгов.
     * @param $item_id
     * @param $tag_ids
     * @return void
     */
    public function update($item_id, $tag_ids)
    {

        $item_tag_ids = $this->getTags($item_id);

        //Оставляем только ID тэгов и превращаем в обычный массив.
        $maskFunc = function($item)
        {
            return $item['id'];
        };

        $item_tag_ids = array_map($maskFunc, $item_tag_ids);

        $item = $this->_em->getReference($this->__itemsTable, $item_id);

        /**
         * Тэги для добавления.
         */
        $diff = array_diff($tag_ids, $item_tag_ids);

        foreach ($diff as $tag) {

            $connect = new \Catalog\Connect();

            $tag_o = $this->_em->getReference($this->__tagsTable, $tag);

            $connect->setItem($item);
            $connect->setTag($tag_o);

            $this->_em->persist($connect);

        }
        $this->_em->flush();

        /**
         * Тэги для удаления.
         */
        $diff = array_diff($item_tag_ids, $tag_ids);

        foreach ($diff as $tag) {

            $connect_id = $this->getOne($item_id, $tag);
            $connect = $this->_em->getReference($this->__table, $connect_id);

            $this->_em->remove($connect);
        }
        $this->_em->flush();

    }

    /**
     * Выводит список (отсортированный) товаров, которые попадают под данные тэги.
     * @param $tags массив ID тэгов.
     * @return массив товаров.
     */
    public function search($tags, $limit = null)
    {

        $res = $this->_em->createQueryBuilder()
                ->select('con', 'item', 'count(tag.id) as matches')
                ->from($this->__table, 'con')
                ->join('con.tag', 'tag')
                ->join('con.item', 'item');

        foreach ($tags as $tag) {
            $res = $res->orWhere('con.tag = ' . $tag);
        }

        $res = $res->groupBy('item.id')
                ->orderBy('matches', 'DESC')
                ->addOrderBy('item.data', 'DESC');

        if ($limit) {

            $res = $res->setMaxResults($limit);

        }

        $res = $res->getQuery()
                ->getArrayResult();

        /**
         * Убираем лишнее с массива. Оставляем только item.
         */
        $maskFunc = function($item)
        {
            return $item[0]['item'];
        };

        $items = array_map($maskFunc, $res);

        return $items;
    }


    public function addTag($tag_array)
    {

        $result = array();


        foreach ($tag_array as $one_tag) {

            $entity = $this->_em->getRepository($this->__tagsTable)->findBy(array('name' => $one_tag));

            if (!$entity) {
                $entity = new \Catalog\Tags();
                $entity->setName($one_tag);
                $entity->setGroup($this->_em->getReference('\Catalog\TagGroup',1));
                $this->_em->persist($entity);
                $this->_em->flush();
                $result[] = $entity->getId();
            }
        }
        return $result;

    }



}
